/*
  ECMFS: Edge Core Master Filesystem - A Distributed Encrypted Filesystem
                                       in Userspace based on FUSE.
  Author    : Harsha M.
  Banner Id : A20250275
  Course    : CS549, Fall 2014, Illinois Institute of Technology, Chicago
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <sys/time.h>
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif
#include <getopt.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include "configfile.h"
#define DEBUG 1

#if DEBUG
#define DEBUG_LOG(fmt, args...) \
    printf("\n[%s][%d] " fmt "\n", __FUNCTION__, __LINE__ , args);
#else
#define DEBUG_LOG(fmt, args...) 
#endif

config_file_parse_ret_t config_file_init(config_file_t *this,
	 const char *config_file_name)
{
	strcpy(this->my_config_file,config_file_name);
    return CONFIG_FILE_READ_OK;
}


config_file_parse_ret_t cfg_write_line(config_file_t *this,config_line_t *line) 
{
	fprintf(this->fd, "%s=%s", line->confVar, line->confValue);
    return CONFIG_FILE_READ_OK;
}

config_file_parse_ret_t cfg_read_line(config_file_t *this,config_line_t *line) 
{
    char ch;
    bool_ecmfs seperator = 0;    
    int conf_var_count = 0; 
    int conf_value_count = 0; 
    while (!feof(this->fd)) { 
        ch = fgetc(this->fd);
        if (feof(this->fd) || (ch == '\n')) {
            break;
        } else if (ch == CONF_SEPERATOR) {
        seperator = 1; 
        } else {
            if (seperator == 0) {
                if (conf_var_count > (CONF_VAR_LEN - 1)) {
                    fprintf(stderr, "conf var too big");
                    return CONFIG_FILE_ERROR;
                }
                line->confVar[conf_var_count] = ch;
                conf_var_count++;
            } else {
                if (conf_value_count > (CONF_VALUE_LEN - 1)) {
                    fprintf(stderr, "conf value too big");
                    return CONFIG_FILE_ERROR;
                }
                line->confValue[conf_value_count] = ch;
                conf_value_count++;
            }
        }
    }

    //if (seperator && strlen(line->confVar) && strlen(line->confValue)) {
        return CONFIG_FILE_READ_OK;
    //} else {
    //    fprintf(stderr,
    //    "config file error:seperator=%d; varlen=[%d]; vallen=[%d]\n", 
    //       seperator, strlen(line->confVar), strlen(line->confValue));
    //    return CONFIG_FILE_ERROR;
    //}
}
config_file_parse_ret_t cfg_open(config_file_t *this,const char *config_file, const char *mode)
{
    if (this->fd) { fclose(this->fd); this->fd=NULL; }
    this->fd = fopen(config_file, mode);
    if (NULL == this->fd) {
        fprintf(stderr, "config file not found");
        return CONFIG_FILE_NOT_FOUND;
    }

    return CONFIG_FILE_READ_OK;
}
config_file_parse_ret_t cfg_ropen(config_file_t *this,const char *config_file)
{
    return cfg_open(this, config_file, "r");
}
config_file_parse_ret_t cfg_wopen(config_file_t *this,const char *config_file)
{
    return cfg_open(this, config_file, "w");
}
config_file_parse_ret_t cfg_aopen(config_file_t *this,char *config_file)
{
    return cfg_open(this, config_file, "a");
}
config_file_parse_ret_t cfg_rwopen(config_file_t *this,char *config_file)
{
    return cfg_open(this, config_file, "rw");
}
config_file_parse_ret_t cfg_close(config_file_t *this)
{
    if (this->fd) { fclose(this->fd); this->fd=NULL; }
    return CONFIG_FILE_READ_OK;
}
config_file_parse_ret_t cfg_read_file(config_file_t *this)
{
    config_file_parse_ret_t ret;
    config_line_t line;
    
    while(!feof(this->fd)) {
        memset(&line, 0, sizeof(config_line_t));
        ret = cfg_read_line(this, &line);
        if (ret != CONFIG_FILE_READ_OK) {
            break;
        }
        cfg_add_to_list(this, &line);
    }

    return ret;
}
config_file_parse_ret_t cfg_write_file(config_file_t *this)
{
    return CONFIG_FILE_WRITE_OK;
}
config_file_parse_ret_t cfg_add_to_list(config_file_t *this, config_line_t *line)
{
    printf("%s=%s\n", line->confVar, line->confValue);

    if (strcmp(line->confVar, "IP") == 0) {
        strncpy(this->my_ip, line->confValue, 32);
    } else if (strcmp(line->confVar, "PORT") == 0) {
        this->my_port = atoi(line->confValue);
    } else if (strcmp(line->confVar, "NODE_OP_TYPE") == 0) {
        if (strcmp(line->confValue, "CLIENT") == 0) {
            this->my_node_type = CONFIG_CLIENT;
        }else {
            return CONFIG_FILE_ERROR;
        }
    } else if (strcmp(line->confVar, "USER_ID") == 0) {
        strncpy(this->user_id, line->confValue, 32);
    } else if (strcmp(line->confVar, "MOUNT_PATH") == 0) {
        strncpy(this->mount_path, line->confValue, 100);
    } else if (strcmp(line->confVar, "MASTER_IP") == 0) {
        strncpy(this->master_ip, line->confValue, 32);
    } else if (strcmp(line->confVar, "MASTER_PORT") == 0) {
        this->master_port = atoi(line->confValue);
    } else if (strcmp(line->confVar, "KEYSTORE") == 0) {
        strncpy(this->keystore_path, line->confValue, 100);
    }
    if (this->write_line < MAX_CONF_VAR) {
	    this->lines[this->write_line] = *line;
	    this->write_line++;
    }
    fprintf(this->fd, "%s=%s\n", 
			line->confVar, line->confValue);
    return CONFIG_FILE_ADD_OK;
}


